﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using DevExpress.XtraGrid.Views.Base;
using Marmat.Forms.Views.DataGrid;


namespace Marmat.Forms
{
    [Designer("Marmat.Forms.Design.DataGridDesigner")]
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(System.Windows.Forms.DataGrid))]
    public partial class DataGrid : BaseGrid, ISupportInitialize, IBindingSource
    {
        public DataGrid()
        {

            // 此调用是设计器所必需的。
            this.DataSource = new DataTable();
            this.InitializeComponent();

            // 在 InitializeComponent() 调用之后添加任何初始化。
            // Me.初始化控件()
        }

        public new bool HasChildren => false;

        bool IBindingSource.AllowEdit
        {
            get => base.Editable;
            set => base.Editable = value;
        }

        private DataRow getDataRow(int index)
        {
            return ((DataRowView)this.BindingSource[index]).Row;
        }

        /* TODO ERROR: Skipped RegionDirectiveTrivia */
        // ''' <summary>
        // ''' 选择不同数据行后执行，也就是Current属性发生变化后执行。
        // ''' </summary>
        // ''' <param name="sender"></param>
        // ''' <param name="e"></param>
        // ''' <remarks></remarks>
        // Private Sub BindingSource_CurrentChanged(sender As Object, e As  Marmat.Forms.Views.Grid.GridEventArgs)
        // If m_Loading = False AndAlso Me.BindingSource.Position <> OldPosition Then
        // Dim Args As New  Marmat.Forms.Views.DataGrid.GridEventArgs(Me)
        // Me.RaiseCurrentChanged()
        // Me.UpdateRelation()
        // End If
        // Me.OldPosition = Me.BindingSource.Position
        // End Sub
        // Private OldPosition As Integer = -1



        /* TODO ERROR: Skipped EndRegionDirectiveTrivia */
        /* TODO ERROR: Skipped RegionDirectiveTrivia */
        /// <summary>
        /// 将行移到指定位置。
        /// </summary>
        /// <param name="row"></param>
        /// <param name="newIndex">新的位置</param>
        /// <remarks></remarks>
        public new void Move(Row row, int newIndex)
        {
            if (string.IsNullOrEmpty(this.SortColumnName) || this.DataSource.Columns.Contains(this.SortColumnName) == false)
            {
                MessageBox.Show("当前表不支持移动行。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            else if (!string.IsNullOrEmpty(this.SortColumnName) && !string.IsNullOrEmpty(this.Sort))
            {
                MessageBox.Show("不能在排序状态下移动行!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            int Count = this.BindingSource.Count;
            int Old_Index = row.Index;
            int New_Index = Math.Min(Math.Max(newIndex, 0), Count - 1);
            decimal Row_Value = -1;
            if (Old_Index != New_Index && New_Index >= 0)
            {
                DataRow dr = ((DataRowView)this.BindingSource[New_Index]).Row;
                if (New_Index == 0 && Count > 0) // 如果新的行号是第一行的话
                {
                    DataRow tmp_row = ((DataRowView)this.BindingSource[0]).Row;
                    Row_Value = Convert.ToDecimal(tmp_row[this.SortColumnName]) - 1;
                    this.OnMove(row, Old_Index, New_Index, Row_Value);
                }
                else if (Old_Index < Count - 1 && New_Index == Count - 1) // 如果新的行号是最后一行的话
                {
                    Row_Value = Convert.ToDecimal(this.DataSource.Compute("MAX(" + this.SortColumnName + ")", "")) + 1m;
                    this.OnMove(row, Old_Index, New_Index, Row_Value);
                }
                else // 如果是上移或下移
                {
                    if (Old_Index > New_Index && Old_Index > 0) // 如果是上移,并且当前行号大于0的话
                    {
                    }
                    else if (Old_Index < newIndex && Old_Index < Count - 1) // 如果是下移，并且当前行号不是最后一行的话
                    {
                        New_Index += 1;
                    }

                    for (int i = 0, loopTo = this.BindingSource.Count - 1; i <= loopTo; i++)
                    {
                        var item = this.getDataRow(i);
                        if (item.IsNull(this.SortColumnName))
                        {
                            if (i == 0)
                            {
                                item[this.SortColumnName] = i;
                            }
                            else if (i < Count - 1)
                            {
                                if (!string.IsNullOrEmpty(this.getDataRow(i + 1)[this.SortColumnName].ToString()))
                                {
                                    decimal o0 = Convert.ToDecimal(this.getDataRow(New_Index - 1)[this.SortColumnName].ToString());
                                    decimal o1 = Convert.ToDecimal(this.getDataRow(New_Index)[this.SortColumnName].ToString());
                                    item[this.SortColumnName] = o1 - (o1 - o0) / 2m;
                                }
                            }
                        }
                    }

                    decimal v0 = Convert.ToDecimal(this.getDataRow(New_Index - 1)[this.SortColumnName].ToString());
                    decimal v1 = Convert.ToDecimal(this.getDataRow(New_Index)[this.SortColumnName].ToString());
                    decimal v2 = v1 - (v1 - v0) / 2m;
                    if (v2 > v0 && v2 < v1)
                    {
                        Row_Value = v2;
                        this.OnMove(row, Old_Index, New_Index, Row_Value);
                    }
                    else
                    {
                        throw new Exception("排序空间不足，请重置排序空间。");
                    }
                }
            }
        }

        private new void OnMove(Row Row, int OldIndex, int NewIndex, decimal Value)
        {
            Row[this.SortColumnName] = Value;
            var EventArgs = new AfterMoveRowEventArgs(this, OldIndex, NewIndex);
            AfterMoveRow?.Invoke(this, EventArgs);
        }

        /// <summary>
        /// 某一列的内容发生变化前执行，此时新值还没有写入表中，列的内容还是更改前的值。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks></remarks>
        private void System_DataTable_ColumnChanging(object sender, System.Data.DataColumnChangeEventArgs e)
        {
            // todo 临时移除,待测试稳定性
            //If m_Loading = True Then Return
            var currentValue = e.Row[e.Column];
            var proposedValue = e.ProposedValue;
            bool changed;

            if (this.Columns.Contains(e.Column.ColumnName))
            {
                changed = !value_Equals(e.Column, currentValue, proposedValue);
                if (changed == true)
                {
                    var eventArgs = new Views.DataGrid.DataColumnChangeEventArgs(this, e);
                    this.DataColChanging?.Invoke(this, eventArgs);

                    if (eventArgs.Cancel == true)
                    {
                        e.ProposedValue = e.Row[e.Column];
                    }
                    else if (eventArgs.Cancel == false)
                    {
                        e.Column.ExtendedProperties.Add(e, false); // false 暂未启用
                    }

                    // 如果属于字符列，并且设置了文本的最大长度，检测输入的字符是否过长，如果过长则自动截短。
                    if (e.Column.DataType == typeof(string) && e.Column.MaxLength != -1)
                    {
                        if (proposedValue is string str && str.Length > e.Column.MaxLength)
                        {
                            System.Windows.Forms.MessageBox.Show(string.Format("\"{0}\"的长度超出了[{1}]列允许的最大长度{2}，将被自动截短！", proposedValue, e.Column.ColumnName, e.Column.MaxLength), "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            e.ProposedValue = str.Substring(0, e.Column.MaxLength);
                        }
                    }
                    else if (eventArgs.Column.Decimals != -1)
                    {
                        if (e.Column.DataType == typeof(double))
                            e.ProposedValue = Math.Round(Convert.ToDouble(proposedValue), eventArgs.Column.Decimals);
                        else if (e.Column.DataType == typeof(float))
                            e.ProposedValue = Math.Round(Convert.ToSingle(proposedValue), eventArgs.Column.Decimals);
                        else if (e.Column.DataType == typeof(decimal))
                            e.ProposedValue = Math.Round(Convert.ToDecimal(proposedValue), eventArgs.Column.Decimals);
                    }

                }
            }
        }

        /// <summary>
        /// 某一列的内容被更改后执行，此时列的内容已经是更改后的值。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks></remarks>
        private void System_DataTable_ColumnChanged(object sender, System.Data.DataColumnChangeEventArgs e)
        {
            // todo 临时移除,待测试稳定性
            // If m_Loading = True Then Return
            bool boo = false;
            foreach (object item in e.Column.ExtendedProperties.Keys)
            {
                if (item is System.Data.DataColumnChangeEventArgs c)
                {
                    if (ReferenceEquals(c.Column, e.Column) && ReferenceEquals(c.Row, e.Row) && ReferenceEquals(c.ProposedValue, e.ProposedValue))
                    {
                        boo = true;
                        e.Column.ExtendedProperties.Remove(item);
                        break;
                    }
                }
            }

            if (boo && this.Columns.Contains(e.Column.ColumnName))
            {
                // If (Me.PrimaryKey Is Nothing OrElse e.Column IsNot Me.PrimaryKey.DataColumn) Then
                boo = false;

                switch (e.Row.RowState)
                {
                    case DataRowState.Added:
                        if (!value_Equals(e.Column, e.Row[e.Column, DataRowVersion.Current], e.ProposedValue))
                            boo = true;
                        break;
                    case DataRowState.Unchanged:
                        if (this.Columns[e.Column.ColumnName].IsTemporary)
                            e.Row.AcceptChanges();
                        else if (value_Equals(e.Column, e.ProposedValue, e.Row[e.Column, DataRowVersion.Original]))
                            e.Row.AcceptChanges();
                        else
                            boo = true;
                        break;
                    case DataRowState.Modified:
                        if (!value_Equals(e.Column, e.Row[e.Column, DataRowVersion.Current], e.ProposedValue))
                            boo = true;
                        break;
                }
                if (boo)
                {
                    e.Row.EndEdit();
                    var args = new Views.DataGrid.DataColumnChangeEventArgs(this, e);
                    DataColChanged?.Invoke(this, args);
                }
            }
            else if (e.Row.RowState == DataRowState.Unchanged)
            {
                e.Row.AcceptChanges();
            }
        }

        private bool value_Equals(DataColumn column, object original, object current)
        {
            bool equals;
            if (object.Equals(original, DBNull.Value))
                original = null;
            if (object.Equals(current, DBNull.Value))
                current = null;

            if (current is null && original is null)
                equals = true;
            else if (column.DataType == typeof(string))
            {
                equals = string.Equals(original, current);
            }
            else if (column.DataType == typeof(double) || column.DataType == typeof(float))
            {
                equals = object.Equals(Convert.ToDecimal(original ?? 0), Convert.ToDecimal(current ?? 0));
            }
            else
                equals = object.Equals(original, current);
            return equals;
        }

        /// <summary>
        /// 插入新 System.Data.DataRow 时发生。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks></remarks>
        private void System_DataTable_TableNewRow(object sender, DataTableNewRowEventArgs e)
        {
            int Index = 1;
            int Count = this.BindingSource.Count;
            if (this.DataSource.Columns.Contains("System_Sort_Temporary"))
            {
                if (Count > 0)
                {
                    var obj = this.getDataRow(this.BindingSource.Count - 1)["System_Sort_Temporary"];
                    if (obj is int value)
                    {
                        Index = value + 1;
                    }
                }
                e.Row["System_Sort_Temporary"] = Index;
            }

            if (this.DataSource.Columns.Contains(this.SortColumnName))
            {
                Index = 1;
                if (Count > 0)
                {
                    var obj = this.getDataRow(this.BindingSource.Count - 1)[this.SortColumnName];
                    if (obj is int value)
                    {
                        Index = value + 1;
                    }
                }

                e.Row[this.SortColumnName] = Index;
            }
        }

        /* TODO ERROR: Skipped EndRegionDirectiveTrivia */
        /* TODO ERROR: Skipped RegionDirectiveTrivia */    // <Editor("Marmat.Forms.BDataGridUITypeEditor", GetType(Drawing.Design.UITypeEditor))>
                                                           // <EditorBrowsable(EditorBrowsableState.Always)>
                                                           // <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
                                                           // Public ReadOnly Property Relation As Relation
                                                           // Get
                                                           // If _Relation Is Nothing Then
                                                           // _Relation = New Relation(Me)
                                                           // End If
                                                           // Return _Relation
                                                           // End Get
                                                           // End Property
                                                           // Private _Relation As Relation


        // <Browsable(False)>
        // Public ReadOnly Property ChildRelation As List(Of Relation)
        // Get
        // If m_ChildRelation Is Nothing Then
        // m_ChildRelation = New List(Of Relation)
        // End If
        // Return m_ChildRelation
        // End Get
        // End Property
        // Private m_ChildRelation As List(Of Relation)


        // ''' <summary>
        // ''' 更新关联显示信息
        // ''' </summary>
        // ''' <remarks></remarks>
        // Private Sub UpdateRelation()
        // If Me.ChildRelation.Count > 0 Then
        // For Each Relation As Relation In Me.ChildRelation
        // Dim filter As New System.Text.StringBuilder
        // If Relation.ChildTable.IsDisposed OrElse Relation.Items.Count = 0 OrElse Relation.SyncLoadMode = SyncLoadModeEnum.None Then Return
        // If Me.CurrentRow IsNot Nothing Then
        // If Relation.ChildTable IsNot Nothing Then
        // For Each Item As RelationColumn In Relation.Items
        // If filter.Length > 0 Then
        // filter.Append(" And ")
        // End If
        // Dim SourceType As BI.Data.SourceType
        // If Me.ConnectionName > "" AndAlso BI.Data.Connections.Contains(Me.ConnectionName) Then
        // SourceType = BI.Data.Connections.Item(Me.ConnectionName).SourceType
        // End If
        // filter.Append("[" & Item.ChildName & "] = " & BI.Data.ViewRowHelper.GetCellValue(Me.CurrentRow.BaseRow, Item.ParentName, DataRowVersion.Default))
        // Next
        // End If
        // Else
        // Relation.ChildTable.Rows.Clear()
        // Relation.ChildTable.AcceptChanges()
        // Exit For
        // End If
        // If Relation.SyncLoadMode = SyncLoadModeEnum.Filter Then
        // Relation.ChildTable.Filter = filter.ToString
        // ElseIf Relation.SyncLoadMode = SyncLoadModeEnum.Load Then
        // Relation.ChildTable.Load(filter.ToString)
        // End If
        // Next
        // End If
        // End Sub
        /* TODO ERROR: Skipped EndRegionDirectiveTrivia */


        [Browsable(false)]
        public new DataTable DataSource
        {
            get
            {
                return (DataTable)base.DataSource;
            }

            set
            {
                if (this.DataSource is object)
                {
                    this.DataSource.TableNewRow -= this.System_DataTable_TableNewRow;
                    this.DataSource.ColumnChanging -= this.System_DataTable_ColumnChanging;
                    this.DataSource.ColumnChanged -= this.System_DataTable_ColumnChanged;
                }
                base.DataSource = value;
                if (value is object)
                {
                    this.DataSource.TableNewRow += this.System_DataTable_TableNewRow;
                    this.DataSource.ColumnChanging += this.System_DataTable_ColumnChanging;
                    this.DataSource.ColumnChanged += this.System_DataTable_ColumnChanged;
                }


            }
        }


        // ''' <summary>
        // ''' 返回或设置当前行位置
        // ''' </summary>
        // <Browsable(False), DefaultValue(CInt(-1))>
        // Public Property Position As Integer
        // Get
        // Return Me.BindingSource.Position
        // End Get
        // Set(ByVal value As Integer)
        // Me.BindingSource.Position = value
        // End Set
        // End Property



        /// <summary>
        /// 返回当前选中行。
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [Browsable(false)]
        public Row CurrentRow
        {
            get
            {
                Row Result = null;
                DataRowView DataRowView = (DataRowView)this.BindingSource.Current;
                if (DataRowView is object)
                {
                    var DataRow = DataRowView.Row;
                    foreach (Row dr in this.Rows)
                    {
                        if (ReferenceEquals(dr.BaseRow, DataRow))
                        {
                            Result = dr;
                            break;
                        }
                    }
                }

                return Result;
            }
        }

        // <EditorAttribute(GetType(Column_Editor), GetType(Drawing.Design.UITypeEditor)),
        // <EditorBrowsable(EditorBrowsableState.Always),
        // DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        // Localizable(True), NotifyParentProperty(True), Category("数据"), Description("返回 Table 的保存集合")>
        // Public ReadOnly Property SaveProjects As SaveProjectCollection
        // Get
        // If m_SaveProjects Is Nothing Then
        // m_SaveProjects = New SaveProjectCollection(Me)
        // End If
        // Return m_SaveProjects
        // End Get
        // End Property
        // Private m_SaveProjects As SaveProjectCollection

        // Private Sub 初始化控件()
        // Me.BaseControl.BringToFront()
        // End Sub

        // <Browsable(False)>
        // Friend ReadOnly Property DataTable As System.Data.DataTable
        // Get
        // If m_DataTable Is Nothing Then
        // m_DataTable = New DataTable
        // End If
        // Return m_DataTable
        // End Get
        // End Property
        // Private WithEvents m_DataTable As System.Data.DataTable

        private BaseView BaseView;

        /// <summary>
        /// 返回 DataGrid 的行集合。
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [Browsable(false)]
        public new RowCollection Rows
        {
            get
            {
                var drs = this.DataSource.Select("", "", DataViewRowState.CurrentRows);
                if (this._RowCollection is null)
                {
                    this._RowCollection = new RowCollection(this, drs);
                }

                this._RowCollection.DataRowCollection = drs;
                return this._RowCollection;
            }
        }

        private RowCollection _RowCollection;

        // Private _ConnectionName As String
        // ''' <summary>
        // ''' 或者或设置 Table 对应的数据源名称
        // ''' </summary>
        // ''' <value></value>
        // ''' <returns></returns>
        // ''' <remarks></remarks>
        // <Editor("Marmat.Forms.BDataGridUITypeEditor", GetType(Drawing.Design.UITypeEditor))>
        // <DefaultValue(CStr(Nothing)), Category("加载"), Description("设置或返回绑定的数据源名称")>
        // Public Property ConnectionName As String
        // Get
        // Return Me._ConnectionName
        // End Get
        // Set(value As String)
        // Me._ConnectionName = value
        // End Set
        // End Property

        // ''' <summary>
        // ''' 获取或设置 Table 对应的数据库后台表名
        // ''' </summary>
        // ''' <value></value>
        // ''' <returns></returns>
        // ''' <remarks></remarks>
        // <Editor("Marmat.Forms.BDataGridUITypeEditor", GetType(Drawing.Design.UITypeEditor))>
        // <DefaultValue(CStr(Nothing)), Category("加载"), Description("获取或设置 Table 对应的数据库后台表名。")>
        // Public Property LoadTableName As String
        // Get
        // Return Me._LoadTableName
        // End Get
        // Set(value As String)
        // Me._LoadTableName = value
        // End Set
        // End Property
        // Private _LoadTableName As String


        // ''' <summary>
        // ''' 获取或设置 Table 的加载条件
        // ''' </summary>
        // ''' <value></value>
        // ''' <returns></returns>
        // ''' <remarks></remarks>
        // <DefaultValue(CStr(Nothing)),
        // Category("加载"), Description("获取或设置 Table 的加载条件。")>
        // Public Property LoadFilter As String
        // Get
        // Return Me._LoadFilter
        // End Get
        // Set(value As String)
        // Me._LoadFilter = value
        // End Set
        // End Property
        // Private _LoadFilter As String

        // ''' <summary>
        // ''' 字符型，指定加载数据的顺序
        // ''' </summary>
        // ''' <value></value>
        // ''' <returns></returns>
        // ''' <remarks></remarks>
        // <DefaultValue(CStr(Nothing))>
        // <Category("加载"), Description("字符型，指定加载数据的顺序。")>
        // Public Property LoadOrder As String
        // Get
        // Return m_LoadOrder
        // End Get
        // Set(value As String)
        // m_LoadOrder = value
        // End Set
        // End Property
        // Private m_LoadOrder As String = Nothing

        /* TODO ERROR: Skipped RegionDirectiveTrivia */    // ''' <summary>
                                                           // ''' 获取或设置是否启用分页加载
                                                           // ''' </summary>
                                                           // ''' <value></value>
                                                           // ''' <returns></returns>
                                                           // ''' <remarks></remarks>
                                                           // <DefaultValue(False)>
                                                           // <Category("加载·分页"), Description("获取或设置是否启用分页加载。")>
                                                           // Public Property ShowPagingLoad As Boolean
                                                           // Get
                                                           // Return Me.m_ShowPagingLoad
                                                           // End Get
                                                           // Set(value As Boolean)
                                                           // Me.m_ShowPagingLoad = value
                                                           // Me.PageControl1.Visible = value
                                                           // End Set
                                                           // End Property
                                                           // Private m_ShowPagingLoad As Boolean = False

        // ''' <summary>
        // ''' 则用于指定每页的行数
        // ''' </summary>
        // ''' <value></value>
        // ''' <returns></returns>
        // ''' <remarks></remarks>
        // <DefaultValue(100)>
        // <Category("加载·分页"), Description("则用于指定每页的行数。")>
        // Public Property LoadTop As Integer
        // Get
        // Return m_LoadTop
        // End Get
        // Set(value As Integer)
        // m_LoadTop = value
        // Me.PageControl1.LoadTop = Me.LoadTop
        // End Set
        // End Property
        // Private m_LoadTop As Integer = 100

        // ''' <summary>
        // ''' 指定要加载的页号
        // ''' </summary>
        // ''' <value></value>
        // ''' <returns></returns>
        // ''' <remarks></remarks>
        // <DefaultValue(1)>
        // <Category("加载·分页"), Description("指定要加载的页号。")>
        // Public Property LoadPage As Integer
        // Get
        // Return m_LoadPage
        // End Get
        // Set(value As Integer)
        // m_LoadPage = value
        // End Set
        // End Property
        // Private m_LoadPage As Integer = 1

        // ''' <summary>
        // ''' 字符型，用于指定分页加载依据列
        // ''' </summary>
        // ''' <value></value>
        // ''' <returns></returns>
        // ''' <remarks></remarks>
        // <DefaultValue(CStr(Nothing))>
        // <Category("加载·分页"), Description("字符型，用于指定分页加载依据列。")>
        // Public Property LoadOver As String
        // Get
        // Return m_LoadOver
        // End Get
        // Set(value As String)
        // m_LoadOver = value
        // End Set
        // End Property
        // Private m_LoadOver As String = Nothing

        // ''' <summary>
        // ''' 逻辑型，是否倒序加载，即是否先加载新数据，此属性只有在分页加载的时候才有效。
        // ''' </summary>
        // ''' <value></value>
        // ''' <returns></returns>
        // ''' <remarks></remarks>
        // <DefaultValue(False)>
        // <Category("加载·分页"), Description("逻辑型，是否倒序加载，即是否先加载新数据，此属性只有在分页加载的时候才有效。")>
        // Public Property LoadReverse As Boolean
        // Get
        // Return m_LoadReverse
        // End Get
        // Set(value As Boolean)
        // m_LoadReverse = value
        // End Set
        // End Property
        // Private m_LoadReverse As Boolean
        /* TODO ERROR: Skipped EndRegionDirectiveTrivia */

        // ''' <summary>
        // ''' 返回加载列名字符串
        // ''' </summary>
        // Friend ReadOnly Property LoadCols As String
        // Get
        // Dim Cols As New System.Text.StringBuilder
        // For Each dc As Views.DataGrid.Column In Me.Columns
        // If dc.IsTemporary = False Then
        // Cols.Append(",[" & dc.Name & "]")
        // End If
        // Next
        // If Cols.Length > 0 Then
        // Cols.Remove(0, 1)
        // End If
        // Return Cols.ToString
        // End Get
        // End Property

        // <Browsable(False)>
        // Public ReadOnly Property PrimaryKey As Marmat.Forms.Views.DataGrid.Column()
        // Get
        // Return m_PrimaryKey.ToArray
        // End Get
        // End Property
        // Friend m_PrimaryKey As New List(Of Marmat.Forms.Views.DataGrid.Column)


        // Private Sub PagingBar1_Paint(sender As Object, e As PaintEventArgs) Handles PageControl1.Paint
        // Dim rect As New Rectangle(0, 0, PageControl1.Width - 1, PageControl1.Height - 1)
        // Using Pen As New Pen(Me.BaseControl.BackColor)
        // e.Graphics.DrawRectangle(Pen, rect)
        // End Using
        // End Sub

        /// <summary>
        /// 获取或设置排序列的字段 ，用于更新排序值
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [Browsable(false)]
        [DefaultValue("")]
        public string SortColumnName
        {
            get
            {
                return this.m_SortColumn;
            }

            set
            {
                this.m_SortColumn = value;
            }
        }

        private string m_SortColumn = "";


        /// <summary>
        /// 返回或设置排序方式。
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [DefaultValue("")]
        [Category("杂项")]
        [Description("返回或设置排序方式。")]
        public override string Sort
        {
            get
            {
                return this._Sort;
            }

            set
            {
                try
                {
                    string sort = "System_Sort_Temporary";
                    this._Sort = value;
                    if (this.DataSource.Columns.Contains("System_Sort_Temporary") == false)
                    {
                        var dc = this.DataSource.Columns.Add("System_Sort_Temporary", typeof(decimal));
                        dc.AutoIncrement = true;
                    }

                    if (!string.IsNullOrEmpty(this.Sort))
                    {
                        var drs = this.DataSource.Select("", this.Sort);
                        for (int i = 0, loopTo = drs.Length - 1; i <= loopTo; i++)
                            drs[i]["System_Sort_Temporary"] = i;
                        sort = "System_Sort_Temporary," + this.Sort;
                    }

                    base.Sort = sort;
                    AfterSort?.Invoke(this, new GridEventArgs(this));
                }
                catch (Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show(ex.ToString(), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private string _Sort = "";

        /// <summary>
        /// 逻辑型，判断DataTable的数据是否已经被修改。
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [Browsable(false)]
        public bool HasChanges
        {
            get
            {
                return this.DataSource.Select("", "", DataViewRowState.Unchanged).Length != this.DataSource.Rows.Count;
            }
        }
        // ''' <summary>
        // ''' 用来异步处理分页加载时页数显示的回调的方法
        // ''' </summary>
        // Private Sub Method_LoadPage()
        // If Me.ShowPagingLoad = True Then
        // '获取总页数--------------------------
        // Dim cmd As New BI.Data.SQLCommand(Me.ConnectionName)
        // cmd.CommandText = "Select Count(*) From [" & Me.LoadTableName & "]" & IIf(Me.LoadFilter > "", "  Where " & LoadFilter, "")
        // '获取总页数-------------------------------------------------------
        // Dim Count As Integer = cmd.ExecuteScalar
        // Me.PageControl1.TotalCount = Count

        // 'Dim Pages As Integer = IIf(Math.Ceiling(Count / Me.LoadTop) > 0, Math.Ceiling(Count / Me.LoadTop), 1)
        // 'If Me.LoadPage > Pages Then
        // '    Me.LoadPage = Pages '直接赋值返回变量
        // 'End If
        // 'Me._TotalPages = Pages
        // 'Me.PageControl1.LoadPage = Me.LoadPage
        // 'Me.PageControl1.TotalPages = Pages
        // 'Me.PageControl1.BarLargeButtonItem1.Caption = String.Format("第{0}/{1}页,共{2}条记录", Me.LoadPage, Pages, Count)
        // End If

        // End Sub

        // ''' <summary>
        // ''' 获取分页的SQL语句
        // ''' </summary>
        // ''' <value></value>
        // ''' <returns></returns>
        // ''' <remarks></remarks>
        // Private ReadOnly Property GetLoadSqlString(ByVal LoadPage As Integer) As String
        // Get
        // Dim Sql As String
        // Dim p As New BI.Data.DataTablePageHelper
        // p.Columns = Me.LoadCols
        // p.Filter = Me.LoadFilter
        // p.Order = Me.LoadOrder
        // p.Over = Me.LoadOver
        // p.Reverse = Me.LoadReverse
        // p.TableName = Me.LoadTableName
        // p.Top = Me.LoadTop
        // If Me.ShowPagingLoad Then
        // Select Case BI.Data.Connections.Item(Me.ConnectionName).ConnectionVersion
        // Case BI.Data.ConnectionVersionEnum.MsSql2005, BI.Data.ConnectionVersionEnum.MsSql2008
        // Sql = p.GetSql2005(LoadPage - 1)
        // Case Else
        // Sql = p.GetSqlString(LoadPage - 1)
        // End Select
        // Else
        // Sql = p.GetSqlString(-1)
        // End If
        // Return Sql
        // End Get
        // End Property


        // Private Sub BPagingBar1_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles PageControl1.ItemClick
        // Me.LoadPage = Me.PageControl1.LoadPage
        // Me.LoadTop = Me.PageControl1.LoadTop
        // 'todo Me.Load() 临时去掉，需要恢复
        // End Sub

        // ''' <summary>
        // ''' 整数型，返回分页加载时，总的可加载总页数。
        // ''' </summary>
        // ''' <value></value>
        // ''' <returns></returns>
        // ''' <remarks></remarks>
        // <Browsable(False)>
        // Public ReadOnly Property TotalPages As Integer
        // Get
        // Return Me._TotalPages
        // End Get
        // End Property
        // Private _TotalPages As Integer

        /* TODO ERROR: Skipped RegionDirectiveTrivia */
        object IBindingSource.GetDataSource()
        {
            return this.BindingSource;
        }

        public BindingFieldInfo[] GetColumnCollection()
        {
            var list = new List<BindingFieldInfo>();
            foreach (Column dc in this.Columns)
            {
                var column = new BindingFieldInfo();
                column.Name = dc.Name;
                column.Caption = dc.Caption;
                column.DataType = dc.DataType;
                column.ReadOnly = !dc.AllowEdit;
                list.Add(column);
            }

            return list.ToArray();
        }
        /* TODO ERROR: Skipped EndRegionDirectiveTrivia */
        // Private Sub DataGrid_BeforeSort(sender As Object, e As BeforeSortEventArgs) Handles MyBase.BeforeSort
        // Me.Sort = e.Sort
        // e.Cancel = True
        // End Sub

        private void DataGrid_RowCellDoubleClick(object sender, Views.Grid.MouseRowColEventArgs e)
        {
            var dc = this.Columns[e.Column.Name];
            var info = new RowColEventArgs(this, e.RowHandle, dc);
            RowCellDoubleClick?.Invoke(this, info);
        }

        private void DataGrid_CustomRowCellEditForEditing(object sender, Views.Grid.CustomRowCellEditEventArgs e)
        {
            var args = new CustomRowCellEditEventArgs(this, e);
            if (this.Editable == false || args.Column.AllowEdit == false)
            {
                e.RepositoryItem = null;
            }

            CustomRowCellEditForEditing?.Invoke(this, args);
        }

        private void DataGrid_CustomRowCellEdit(object sender, Views.Grid.CustomRowCellEditEventArgs e)
        {
            var info = new CustomRowCellEditEventArgs(this, e);
            CustomRowCellEdit?.Invoke(this, info);
        }

        private void DataGrid_ShowingEditor(object sender, Views.Grid.RowColCancelEventArgs e)
        {
            var dc = this.Columns[e.Column.Name];
            var info = new RowColCancelEventArgs(this, e.RowHandle, dc, e._e);
            ShowingEditor?.Invoke(this, info);
        }

        private void DataGrid_CustomColumnDisplayText(object sender, Views.Grid.CustomColumnDisplayTextEventArgs e)
        {
            var args = new Views.DataGrid.CustomColumnDisplayTextEventArgs(e.info);
            args._GridControl = this;
            CustomColumnDisplayText?.Invoke(this, args);
        }

        private void DataGrid_ShownEditor(object sender, Views.Grid.RowColEventArgs e)
        {
            var dc = this.Columns[e.Column.Name];
            var info = new RowColEventArgs(this, e.RowHandle, dc);
            ShownEditor?.Invoke(this, info);
        }

        private void DataGrid_ValidatingEditor(object sender, Views.Grid.ValidateEditEventArgs e)
        {
            var info = new ValidateEditEventArgs(e);
            ValidatingEditor?.Invoke(sender, info);
        }

        private void DataGrid_CustomColumnGroup(object sender, Views.Grid.CustomColumnSortEventArgs e)
        {
            var Info = new Views.DataGrid.CustomColumnSortEventArgs(this, e);
            CustomColumnGroup?.Invoke(this, Info);
        }

        private void DataGrid_CustomColumnSort(object sender, Views.Grid.CustomColumnSortEventArgs e)
        {
            var Info = new Views.DataGrid.CustomColumnSortEventArgs(this, e);
            CustomColumnSort?.Invoke(this, Info);
        }

        private void DataGrid_CellValueChanged(object sender, Views.Grid.CellValueChangingEventArgs e)
        {
            var dc = this.Columns[e.Column.Name];
            var info = new CellValueChangingEventArgs(this, e.RowHandle, dc, e.Value);
            CellValueChanged?.Invoke(this, info);
        }

        private void DataGrid_CellValueChanging(object sender, Views.Grid.CellValueChangingEventArgs e)
        {
            var dc = this.Columns[e.Column.Name];
            var info = new CellValueChangingEventArgs(this, e.RowHandle, dc, e.Value);
            CellValueChanging?.Invoke(this, info);
        }

        private void DataGrid_ColumnWidthChanged(object sender, Views.Grid.ColumnEventArgs e)
        {
            var info = new Views.DataGrid.ColumnEventArgs(this, e.info);
            ColumnWidthChanged?.Invoke(this, info);
        }

        private void DataGrid_FocusedColumnChanged(object sender, Views.Grid.FocusedColumnChangedEventArgs e)
        {
            var info = new Views.DataGrid.FocusedColumnChangedEventArgs(this, e.info);
            FocusedColumnChanged?.Invoke(this, info);
        }

        private void DataGrid_FocusedRowChanged(object sender, Views.Grid.FocusedRowChangedEventArgs e)
        {
            var info = new Views.DataGrid.FocusedRowChangedEventArgs(e.sender, e.info);
            FocusedRowChanged?.Invoke(this, info);
        }

        private void DataGrid_SelectionChanged(object sender, Views.Grid.SelectionChangedEventArgs e)
        {
            var info = new SelectionChangedEventArgs(e.info);
            SelectionChanged?.Invoke(this, info);
        }

        private void DataGrid_BeforeLeaveRow(object sender, Views.Grid.RowAllowEventArgs e)
        {
            var info = new Views.DataGrid.RowAllowEventArgs(e.info);
            BeforeLeaveRow?.Invoke(this, info);
        }

        private void DataGrid_InvalidRowException(object sender, Views.Grid.InvalidRowExceptionEventArgs e)
        {
            var info = new Views.DataGrid.InvalidRowExceptionEventArgs(e.Info);
            InvalidRowException?.Invoke(this, info);
        }

        private void DataGrid_InvalidValueException(object sender, Views.Grid.InvalidValueExceptionEventArgs e)
        {
            var info = new Views.DataGrid.InvalidValueExceptionEventArgs(e.info);
            InvalidValueException?.Invoke(this, info);
        }

        private void DataGrid_RowCellClick(object sender, Views.Grid.MouseRowColEventArgs e)
        {
            var dc = this.Columns[e.Column.Name];
            var info = new RowColEventArgs(this, e.RowHandle, dc);
            RowCellClick?.Invoke(this, info);
        }

        private void DataGrid_RowClick(object sender, Views.Grid.RowClickEventArgs e)
        {
            var info = new RowClickEventArgs(e.info);
            RowClick?.Invoke(this, info);
        }

        private void DataGrid_ValidateRow(object sender, Views.Grid.ValidateRowEventArgs e)
        {
            var info = new Views.DataGrid.ValidateRowEventArgs(e.info);
            ValidateRow?.Invoke(this, info);
        }

        private void DataGrid_CurrentChanged(object sender, Views.Grid.GridEventArgs e)
        {
            if (this.open_currentChangedEvent)
            {
                var info = new GridEventArgs(this);
                CurrentChanged?.Invoke(this, info);
            }
        }

        private void DataGrid_PositionChanged(object sender, Views.Grid.GridEventArgs e)
        {
            var info = new GridEventArgs(this);
            PositionChanged?.Invoke(this, info);
        }

        private void DataGrid_CellButtonClick(object sender, Views.Grid.RowColEventArgs e)
        {
            var dc = this.Columns[e.Column.Name];
            var info = new RowColEventArgs(this, e.RowHandle, dc);
            CellButtonClick?.Invoke(this, info);
        }

        private void DataGrid_CellLinkClick(object sender, Views.Grid.MouseRowColEventArgs e)
        {
            var dc = this.Columns[e.Column.Name];
            var info = new RowColEventArgs(this, e.RowHandle, dc);
            CellLinkClick?.Invoke(this, info);
        }

        private void DataGrid_CellMerge(object sender, Views.Grid.CellMergeEventArgs e)
        {
            var info = new CellMergeEventArgs(this, e);
            CellMerge?.Invoke(this, info);
        }

        private void DataGrid_CustomDrawCell(object sender, Views.Grid.RowCellCustomDrawEventArgs e)
        {
            var info = new Views.DataGrid.RowCellCustomDrawEventArgs(this, e.info);
            if (!ReferenceEquals(info.CellValue, DBNull.Value))
            {
                if ((info.Column.DataType == typeof(float) || info.Column.DataType == typeof(double) || info.Column.DataType == typeof(decimal)) && info.Column.Decimals > 0)
                {
                    var fomat = $"{{0:0.{new string('0', info.Column.Decimals)}}}";
                    info.DisplayText = string.Format(fomat, info.CellValue);
                }
            }
            CustomDrawCell?.Invoke(this, info);
        }

        private void DataGrid_CustomDrawColumnHeader(object sender, Views.Grid.ColumnHeaderCustomDrawEventArgs e)
        {
            var info = new ColumnHeaderCustomDrawEventArgs(e.args);
            info._GridControl = this;
            CustomDrawColumnHeader?.Invoke(this, info);
        }
    }
}